﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Text;
using System.Net.Mail;
using YEA.Utilities.Logging;
using YEA.Utilities.Notifications;

namespace YEA.Utilities
{
    public class ExceptionManager : YEA.Utilities.IExceptionManager
    {
        public const string NotificationToEmail = "notificationToEmail";
        public const string NotificationFromEmail = "notificationFromEmail";
        public ILog Logger { get; set; }
        public INotify Notifier { get; set; }
        public MailAddressCollection Emails{ get; private set;}
        public MailAddress From { get; private set; }
        public ExceptionManager(ILog logger, INotify notifier)
        {
            Emails = new MailAddressCollection();
            Logger = logger;
            Notifier = notifier;
            Initialize();
        }

        public ExceptionManager()
        {
            Logger = new Logger("logExchange");
            Notifier = new Notifier("notificationExchange");
            Initialize();
        }

        protected void Initialize()
        {
            if( string.IsNullOrWhiteSpace(ConfigurationManager.AppSettings[NotificationToEmail] ) )
                //throw new ArgumentException( string.Format("the key {0} app setting is required", NotificationToEmail));
            if (string.IsNullOrWhiteSpace(ConfigurationManager.AppSettings[NotificationFromEmail]))
                throw new ArgumentException( string.Format("the key {0} app setting is required", NotificationFromEmail));
            Emails = new MailAddressCollection();
            var stremails = ConfigurationManager.AppSettings[NotificationToEmail];
            foreach (var email in stremails.Split(',',';'))
                Emails.Add(new MailAddress(email));
            From = new MailAddress(ConfigurationManager.AppSettings[NotificationFromEmail]); 
        }
        public bool ManageException(Exception ex)
        {
            return this.ManageException(ex, LogType.Error);
        }
        /// <summary>
        /// Manages exceptions
        /// </summary>
        /// <param name="ex">the exception</param>
        /// <param name="loglevel">the severity level of the exception</param>
        /// <returns>true if succeeded in managing exception, otherwise false</returns>
        public bool ManageException(Exception ex, LogType loglevel)
        {
            if (ex == null)
                return true;
            try
            {
                var message = ExceptionToString(ex);
                Logger.Write(message, loglevel);
                using (var n = new Notification() { Body = message, Subject = ex.Message, From = From })
                {
                    foreach (var address in Emails)
                        n.To.Add(address);
                    Notifier.Transmit(n);
                }
            }
            catch
            {
                return false;
            }
            return true;
        }
        protected string ExceptionToString(Exception ex)
        {
            if (ex != null)
                throw new ArgumentException("The parameter ex has to be passed to the method");
            var strb = new StringBuilder(ex.Message);
            strb.AppendLine( "Source: " + ex.Source);
            strb.AppendLine("TargetSite: " + ex.TargetSite.ToString());
            strb.AppendLine("StackTrace: " + ex.StackTrace);
            if (ex.Data.Count > 0)
                strb.AppendLine("data");
            foreach (var data in ex.Data)
                strb.AppendLine( data.ToString());
            if (ex.InnerException != null)
                strb.Append(ExceptionToString(ex.InnerException));
            return strb.ToString();
        }
    }
}
